import pandas as pd
import Core.Gadget as Gadget
import Core.MongoDB as MongoDB
import numpy as np
import Core.IO as IO
import math
import statsmodels.api as sm
import matplotlib.pyplot as plt
import matplotlib.dates as mdate
import datetime

def StockList():
    trades = database.find("Instruments", "Stock")
    symbols = []
    for trade in trades:
        symbol = trade["Symbol"]
        symbols.append(symbol)
    return symbols

def StockAnalyse(dates, no_of_stocks, initial , slip , cost , trade_detail = True , soha = True):

    symbols = StockList()
    #symbols =["600762.SH", "000001.SZ", "000002.SZ","000005.SZ"]
    Stock_info = {}
    cash = 0
    position = {}
    net = initial
    net_value_curve = []
    j = 0
    while j < len(dates):
        datetime_cal = dates[j]
        for symbol in symbols:
            datetime_before = datetime_cal - datetime.timedelta(days=300)
            quotes = database.find("Quote", symbol + "_Time_86400_Bar", datetime_before, datetime_cal)
            if len(quotes) <= 2:
                continue
            quote = quotes[len(quotes) - 1]
            quote_lastday = quotes[len(quotes) - 2]
            factors_BTM = database.find("Factor", "BookToMarket", datetime_before, datetime_cal, query={"Symbol": symbol})
            factors_PE = database.find("Factor", "PriceEarningNetIncomeTTM", datetime_before, datetime_cal,
                                        query={"Symbol": symbol})
            factors_EBITTEV = database.find("Factor", "EBITTEVTTM", datetime_before, datetime_cal,
                                       query={"Symbol": symbol})
            if not factors_BTM:
                continue
            factor_BTM = factors_BTM[len(factors_BTM) - 1]
            if not factors_PE:
                continue
            factor_PE = factors_PE[len(factors_PE) - 1]
            if not factors_EBITTEV:
                continue
            factor_EBITTEV = factors_EBITTEV[len(factors_EBITTEV) - 1]
            if symbol not in Stock_info:
                doc = {}
                doc["Symbol"] = symbol
                doc["StdDateTime"] = quote["StdDateTime"]
                doc["Price"] = quote["Close"]
                doc["AdjFactor"] = 1
                doc["BTM"] = factor_BTM["Value"]
                doc["MV"] = quote["Close"] * quote["Values"]["TotalShares"]
                doc["PE"] = factor_PE["Value"]
                doc["EBITTEV"]= factor_EBITTEV["Value"]
                doc["PTEV"]= factor_PE["Value"] * factor_EBITTEV["Value"]
                Stock_info[symbol] = doc
            Stock_info[symbol]["Price"] = quote["Close"]
            Stock_info[symbol]["BTM"] = factor_BTM["Value"]
            Stock_info[symbol]["PE"] = factor_PE["Value"]
            Stock_info[symbol]["EBITTEV"] = factor_EBITTEV["Value"]
            Stock_info[symbol]["PTEV"] = factor_PE["Value"] * factor_EBITTEV["Value"]
            Stock_info[symbol]["MV"] = quote["Close"] * quote["Values"]["TotalShares"]
            Stock_info[symbol]["StdDateTime"] = quote["StdDateTime"]


        df = pd.DataFrame(columns=('Symbol', "PE", "EBITTEV","PTEV", "Order"))  # 生成空的pandas表
        i = 0
        for symbol in Stock_info:  # 插入一行
            df.loc[i] = [Stock_info[symbol]["Symbol"],Stock_info[symbol]["PE"],
                         Stock_info[symbol]["EBITTEV"] ,Stock_info[symbol]["PTEV"], None]
            i += 1
        df_order_by_PE = df.sort_values(by=["PE"])#从小到大排序
        for i in range(len(df_order_by_PE)):
            df_order_by_PE.iloc[i,4] = i

        df_order_by_EBITTEV = df.sort_values(by=["EBITTEV"],ascending=False)#从大到小排序
        for i in range(len(df_order_by_EBITTEV)):
            df_order_by_EBITTEV.iloc[i,4] = i
        for i in range(len(df)):
            df.loc[i,'Order']= df_order_by_PE.loc[i,"Order"] + df_order_by_EBITTEV.loc[i,"Order"]
        df_order_by_Order = df.sort_values(by=["Order"])


        top_stocks = df_order_by_Order  # 索引需要注意：pandas前闭后开，包括前不包括后
        top_stocks = np.array(top_stocks)  # np.ndarray()
        top_stocks = top_stocks.tolist()  # list
        top_n_stocks = []
        for i in range(len(top_stocks)):
            symbol = top_stocks[i][0]
            quotes = database.find("Quote", symbol + "_Time_86400_Bar", datetime_before, datetime_cal)
            if len(quotes) > 0:
                quote = quotes[len(quotes) - 1]
                if quote["StdDateTime"] > datetime_cal - datetime.timedelta(days=10) and len(
                        top_n_stocks) < no_of_stocks:
                    top_n_stocks.append(top_stocks[i])
        print(top_n_stocks)

        if len(position) > 0:
            for symbol in position:
                if symbol == "600762.SH":
                    alll = 1
                quotes = database.find("Quote", symbol + "_Time_86400_Bar", datetime_before, datetime_cal)
                quote = quotes[len(quotes) - 1]
                profit = (quote["Close"]- position[symbol]["Price"]) * position[symbol]["Volume"]
                net = net + profit - slip  * position[symbol]["Volume"] - (quote["Close"]+ position[symbol]["Price"]) * position[symbol]["Volume"]* cost
                if trade_detail:
                    print(IO.ToDateString(quote["StdDateTime"]), "Sell: " + symbol , position[symbol]["Volume"],"shares at " , quote["Close"] ,
                      "Cashflow: " , quote["Close"]* position[symbol]["Volume"], "Net Value: " , net)
            position = {}


        if len(position) == 0:
            for i in range(len(top_n_stocks)):
                symbol = top_n_stocks[i][0]
                if symbol not in position:
                    if symbol == "600762.SH":
                        alll = 1
                    quotes = database.find("Quote", symbol + "_Time_86400_Bar", datetime_before, datetime_cal)
                    quote = quotes[len(quotes) - 1]
                    doc = {}
                    doc["Price"] = quote["Close"]
                    if soha:
                        doc["Volume"] = math.floor((net / no_of_stocks) / (quote["Close"] * 100)) * 100
                    else:
                        doc["Volume"] = math.floor((initial / no_of_stocks) / (quote["Close"] * 100)) * 100
                    doc["Cost"] = quote["Close"] * math.floor((initial / no_of_stocks) / (quote["Close"] * 100)) * 100
                    position[symbol] = doc
                    if trade_detail:
                        print(IO.ToDateString(quote["StdDateTime"]), "Buy: " + symbol, doc["Volume"], "shares at ",
                              doc["Price"],
                              "Cashflow: -", doc["Cost"], "Net Value: ", net)


        net_value_curve.append([quote["StdDateTime"],net])
        j += 1
    for i in range(len(net_value_curve)):
        print(net_value_curve[i])

def Top_stock_list(datetime1, no_of_stocks):
    trades = database.find("Instruments", "Stock")
    symbols = []
    for trade in trades:
        if trade["DateTime2"] < Gadget.ToUTCDateTime(datetime1):
            continue
        symbol = trade["Symbol"]
        symbols.append(symbol)
    #symbols =["600762.SH", "000001.SZ", "000002.SZ","000005.SZ"]
    Stock_info = {}
    datetime_cal = datetime1
    count = 0
    for symbol in symbols:
        datetime_before = datetime_cal - datetime.timedelta(days=100)
        factors_PE = database.find("Factor", "PriceEarningNetIncomeTTM", datetime_before, datetime_cal,
                                   query={"Symbol": symbol})
        factors_EBITTEV = database.find("Factor", "EBITTEVTTM", datetime_before, datetime_cal,
                                        query={"Symbol": symbol})
        if not factors_PE:
            continue
        factor_PE = factors_PE[-1]
        if not factors_EBITTEV:
            continue
        factor_EBITTEV = factors_EBITTEV[-1]
        quotes = database.find("Quote", symbol + "_Time_86400_Bar", factor_EBITTEV["StdDateTime"] ,
                               datetime1)
        if len(quotes)<2:
            continue
        quote = quotes[-1]
        quote_reportdate = quotes[0]
        if symbol not in Stock_info:
            doc = {}
            doc["Symbol"] = symbol
            doc["StdDateTime"] = factor_EBITTEV["StdDateTime"]
            doc["PE"] = (factor_PE["Value"]/(quote["Close"]*quote["Values"]["TotalShares"]))*(quote_reportdate["Close"]*quote_reportdate["Values"]["TotalShares"])
            doc["EBITTEV"] = factor_EBITTEV["Value"]
            Stock_info[symbol] = doc

        count += 1

        print(symbol, count)

    df = pd.DataFrame(columns=('Symbol', "PE", "EBITTEV", "Order"))  # 生成空的pandas表
    i = 0
    for symbol in Stock_info:  # 插入一行
        df.loc[i] = [Stock_info[symbol]["Symbol"], Stock_info[symbol]["PE"],
                     Stock_info[symbol]["EBITTEV"], None]
        i += 1
    df_order_by_PE = df.sort_values(by=["PE"])  # 从小到大排序
    for i in range(len(df_order_by_PE)):
        df_order_by_PE.iloc[i, 3] = i

    df_order_by_EBITTEV = df.sort_values(by=["EBITTEV"], ascending=False)  # 从大到小排序
    for i in range(len(df_order_by_EBITTEV)):
        df_order_by_EBITTEV.iloc[i, 3] = i
    for i in range(len(df)):
        df.loc[i, 'Order'] = df_order_by_PE.loc[i, "Order"] + df_order_by_EBITTEV.loc[i, "Order"]
    df_order_by_Order = df.sort_values(by=["Order"])

    top_stocks = df_order_by_Order  # 索引需要注意：pandas前闭后开，包括前不包括后
    top_stocks = np.array(top_stocks)  # np.ndarray()
    top_stocks = top_stocks.tolist()  # list
    top_n_stocks = []
    for i in range(len(top_stocks)):
        if len(top_n_stocks) < no_of_stocks:
            top_n_stocks.append(top_stocks[i])

    print("股票代码","市盈率","资产收益率","综合总和")

    for i in range(len(top_n_stocks)):
        print(top_n_stocks[i][0],top_n_stocks[i][1],top_n_stocks[i][2],top_n_stocks[i][3])





from Core.Config import Config
config = Config()
database = config.DataBase()
datetime1 = datetime.datetime(2004, 5, 2)
datetime1 = Gadget.ToUTCDateTime(datetime1)
datetime2 = datetime.datetime(2018, 11, 15)
datetime2 = Gadget.ToUTCDateTime(datetime2)
dates = Gadget.GenerateReleaseDates(datetime1,datetime2)
initial = 1000000
slip = 0.01
cost = 0.0005
#for i in range(len(dates)):
#    sz_index = database.find("Index", "000001.SH_Time_86400_Bar", dates[i] - datetime.timedelta(days=10),dates[i])
#    print (IO.ToDateString(dates[i]),sz_index[-1]["Close"])

#StockAnalyse(dates, 20, initial , slip = 0.01 , cost = 0.0005 , trade_detail = True ,soha = True ) #更新市场因子，价值因子，和公司规模因子，需要手动输入至fama1文件里
Top_stock_list(Gadget.ToUTCDateTime(datetime.datetime(2018, 11, 22)), 20)
